using Sirenix.OdinInspector;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace Custom.Daily.Toolkit
{
    [AddComponentMenu("刮刮乐效果")]
    public class ScratchCard : MonoBehaviour, IDragHandler
    {
        [SerializeField, Range(1, 100),LabelText("擦除范围")]
        private int radius = 10;
        [SerializeField, Range(0, 1), LabelText("擦除完成度")]
        private float complete;
        [SerializeField, LabelText("笔刷颜色")]
        private Color color = Color.clear;
        [SerializeField, LabelText("擦除成功后的回调")]
        public UnityEvent callback;

        // 擦除的像素数量
        private int _pixelCount = 0;
        //是否擦除成功
        private bool _isDrag = false;
        // RawImage 组件
        private RawImage _rawImage;
        // 存储图片的原始纹理,不可修改
        private Texture2D _originalTexture2DNotModify;
        // 存储图片的原始纹理,可修改
        private Texture2D _originalTexture2DYesModify;
        // 存放像素点
        private int[][] _pixelArray;
        // 存放位置对应的像素点
        private Dictionary<int, TexturePixel> _texPixelDict;
        // 布尔数组，记录每个像素是否已被擦除
        private bool[,] _erasedPixelsMap; 
        void Start()
        {
            _rawImage = GetComponent<RawImage>();
            _texPixelDict = new();
            AgainStart();
        }
        /// <summary>
        ///  拖拽中
        /// </summary>
        /// <param name="eventData">拖拽数据</param>
        public void OnDrag(PointerEventData eventData)
        {
            if (_isDrag) return;
            var posA = ScreenPoint2Pixel(eventData.position);
            ChangePixelColorByCircle((int)posA.x, (int)posA.y);
            SetAllPixelFadeAlpha();
        }

        # region 外部使用接口
        /// <summary>
        /// 更换图片/刷新 调用此方法
        /// </summary>
        [Button("图片复位", ButtonHeight = 30)]
        public void AgainStart()
        {
            AgainStart(null);
        }
        public void AgainStart(Texture2D texture2D)
        {
            if (texture2D != null)
            {
                // 换图
                _rawImage.texture = texture2D;
                // 保存图片的原始纹理
                _originalTexture2DNotModify = texture2D;
            }
            else
            {
                if (_originalTexture2DNotModify != null)
                {
                    _rawImage.texture = _originalTexture2DNotModify;
                }
                else
                {
                    var texture = _rawImage.texture as Texture2D;
                    // 获取 RawImage 并转换成 Texture2D
                    if (texture == null)
                    {
                        Debug.LogError("图片转换Texture2D失败!");
                        return;
                    }
                    // 保存图片的原始纹理
                    _originalTexture2DNotModify = texture;
                }
            }
            // 保存一个图片的原始纹理,后续需要修改
            _originalTexture2DYesModify = DailyToolkitTools.DuplicateTexture(_originalTexture2DNotModify);
            _erasedPixelsMap = new bool[_originalTexture2DYesModify.width, _originalTexture2DYesModify.height];
            _isDrag = false;
            _pixelCount = 0;
            _rawImage.color = new Color(1f, 1f, 1f, 1f);
            _rawImage.texture = _originalTexture2DYesModify;
            _texPixelDict.Clear();
            
            Init();
        }
        # endregion

        /// <summary>
        /// 初始化记录所有像素点
        /// </summary>
        private void Init()
        {
            var value = 0;
            _pixelArray = new int[_originalTexture2DYesModify.width][];
            for (var i = 0; i < _pixelArray.Length; i++)
            {
                _pixelArray[i] = new int[_originalTexture2DYesModify.height];
                for (var j = 0; j < _originalTexture2DYesModify.height; j++)
                {
                    _pixelArray[i][j] = value;

                    _texPixelDict.Add(value, new TexturePixel(_originalTexture2DYesModify, i, j));
                    value++;
                }
            }
        }
        
        /// <summary>
        ///  改变Texture2D像素点颜色
        /// </summary>
        /// <param name="x">Texture2D像素点X轴位置</param>
        /// <param name="y">Texture2D像素点Y轴位置</param>
        private void ChangePixelColorByCircle(int x, int y)
        {
            for (var i = -radius; i <= radius; i++)
            {
                var py = y + i;
                if (py < 0 || py >= _originalTexture2DYesModify.height)
                {
                    continue;
                }

                for (var j = -radius; j <= radius; j++)
                {
                    var px = x + j;
                    if (px < 0 || px >= _originalTexture2DYesModify.width)
                    {
                        continue;
                    }

                    if (new Vector2(px - x, py - y).magnitude > radius)
                    {
                        continue;
                    }

                    // 检查像素是否已被擦除
                    if (!_erasedPixelsMap[px, py])
                    {
                        TexturePixel tp = _texPixelDict[_pixelArray[px][py]];

                        // 如果像素还没有被擦除，则计数
                        if (!tp.GetPixel())
                        {
                            _pixelCount++;
                            tp.Scratch(color);
                            _erasedPixelsMap[px, py] = true; // 标记像素已被擦除
                        }
                    }
                }
            }
            _originalTexture2DYesModify.Apply();
        }

        /// <summary>
        ///  擦除点
        /// </summary>
        /// <param name="mousePos">鼠标位置</param>
        /// <returns>擦除点</returns>
        private Vector2 ScreenPoint2Pixel(Vector2 mousePos)
        {
            var sizeDelta = _rawImage.rectTransform.sizeDelta;
            var imageWidth = sizeDelta.x;
            var imageHeight = sizeDelta.y;
            var imagePos = _rawImage.rectTransform.anchoredPosition3D;
            //求鼠标在image上的位置
            var horizontalPercent =
                (mousePos.x - (Screen.width / 2 + imagePos.x - imageWidth / 2)) / imageWidth; //鼠标在Image 水平上的位置  %
            var verticalPercent =
                (mousePos.y - (Screen.height / 2 + imagePos.y - imageHeight / 2)) / imageHeight; //鼠标在Image 垂直上的位置  %
            var x = horizontalPercent * _originalTexture2DYesModify.width;
            var y = verticalPercent * _originalTexture2DYesModify.height;
            return new Vector2(x, y);
        }

        /// <summary>
        ///  擦除完成时调用
        /// </summary>
        private void SetAllPixelFadeAlpha()
        {
            if (!(++_pixelCount >= _originalTexture2DYesModify.height * _originalTexture2DYesModify.width * complete)) return;
            _rawImage.color = Color.clear;
            _isDrag = true;
            callback?.Invoke();
            Debug.Log("擦除完成");
        }
        
        private class TexturePixel
        {
            private readonly Texture2D _myTexture2D;
            private readonly int _x;      //像素坐标X
            private readonly int _y;      //像素坐标Y
            public TexturePixel(Texture2D tex, int x, int y)
            {
                _myTexture2D = tex;
                this._x = x;
                this._y = y;
            }
            public void Scratch(Color targetCol)
            {
                _myTexture2D.SetPixel(_x, _y, targetCol);
            }

            public bool GetPixel()
            {
                var color = _myTexture2D.GetPixel(_x, _y);
                return color.a <= 0;
            }
        }
    }
}
